package com.tinem.platform.web.netty.websocket.session;

import com.tinem.platform.module.starter.sdk.page.PlatformJwt;
import io.netty.channel.ChannelHandlerContext;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author fengzhihao
 * @version v1
 * @program: platform
 * @className Session
 * @description TODO
 * @site
 * @company
 * @create 2021/12/2 16:25:42
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Session {
    static Lock lock = new ReentrantLock();
    static ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
    /**
     * 用户session 集合
     */
    public final static Map<String, List<Session>> userSessionMap = new ConcurrentHashMap<>();
    /**
     * channel 的session 信息
     */
    public final static Map<String, Session> channelSession = new ConcurrentHashMap<>();

    PlatformJwt jwt;
    ChannelHandlerContext ctx;
    Set<String> connectionIdSet=new ConcurrentSkipListSet<>();

    public Session(ChannelHandlerContext ctx){
        this.ctx=ctx;
    }

    public static void addSession(ChannelHandlerContext ctx){
        channelSession.put(ctx.channel().id().asLongText(),new Session(ctx));
    }
    public static void addConsumerId(ChannelHandlerContext ctx, String connectionId){
        channelSession.get(ctx.channel().id().asLongText()).getConnectionIdSet().add(connectionId);
    }
    public static Session getSession(ChannelHandlerContext ctx){
        return channelSession.get(ctx.channel().id().asLongText());
    }

    public static void auth(Session session){
        reentrantReadWriteLock.readLock().lock();
        try {
            List<Session> userSessions = userSessionMap.get(session.getJwt().getUserId());
            if(userSessions == null){
                lock.lock();
                try {
                    userSessions = userSessionMap.get(session.getJwt().getUserId());
                    if(userSessions == null){
                        userSessions = new CopyOnWriteArrayList<>();
                        userSessionMap.put(session.getJwt().getUserId(),userSessions);
                    }
                }finally {
                    lock.unlock();
                }
            }
            userSessions.add(session);
        }finally {
            reentrantReadWriteLock.readLock().unlock();
        }
    }
    public static void closeSession(Session session){
        session.getCtx().close();
        channelSession.remove(session.getCtx().channel().id().asLongText());
        if(session.getJwt() == null){
            return;
        }
        reentrantReadWriteLock.readLock().lock();
        try {
            List<Session> userSessions = userSessionMap.get(session.getJwt().getUserId());
            userSessions.remove(session);
            if(userSessions.size()==0){
                reentrantReadWriteLock.readLock().unlock();
                reentrantReadWriteLock.writeLock().lock();
                try {
                    userSessionMap.remove(session.getJwt().getUserId());
                }finally {
                    reentrantReadWriteLock.writeLock().unlock();
                    reentrantReadWriteLock.readLock().lock();
                }
            }
        }finally {
            reentrantReadWriteLock.readLock().unlock();
        }
    }
}
